<template>
  <div class="app-container">
    <el-row>
      <hot-table
        id="hot"
        ref="hotTableComponent"
        :data="data"
        :settings="hotSettings"
      >
      </hot-table>
    </el-row>
    <el-row>
      <el-tabs v-model="activeName">
        <el-tab-pane label="基本信息" name="basicInfo">
          <el-descriptions title="">
            <!-- <el-descriptions-item label="主诊断">
              {{ userinfo.discode }}-{{ userinfo.disname }}
            </el-descriptions-item>

            <el-descriptions-item label="病组"
              >{{ userinfo.drgcode }}-{{
                userinfo.drgname
              }}</el-descriptions-item
            >

            <el-descriptions-item label="手术编码"
              >{{ userinfo.optcode }}-{{
                userinfo.optname
              }}</el-descriptions-item
            > -->

            <el-descriptions-item label="路径ID">{{
              patwayinfo.ID
            }}</el-descriptions-item>
            <el-descriptions-item label="路径名称">{{
              patwayinfo.名称
            }}</el-descriptions-item>

            <el-descriptions-item label="路径版本">{{
              vn(userinfo.drgcode)
            }}</el-descriptions-item>
          </el-descriptions>
        </el-tab-pane>

        <!-- <el-tab-pane label="应用于以下疾病" name="second">
          <el-table
            ref="multipleTable"
            :row-key="getRowKeys"
            :data="
              disePaths.slice(
                (disePathsPage - 1) * disePathsSize,
                disePathsPage * disePathsSize
              )
            "
            tooltip-effect="dark"
            style="width: 100%"
            @selection-change="handleSelectionChange"
          >
            <el-table-column
              type="selection"
              width="55"
              :reserve-selection="true"
            >
            </el-table-column>

            <el-table-column prop="疾病编码" label="疾病编码" width="120">
            </el-table-column>
            <el-table-column prop="名称" label="名称" show-overflow-tooltip>
            </el-table-column>
          </el-table>

          <div class="block">
            <el-pagination
              @size-change="disePathsbasicCostHandleSizeChange"
              @current-change="disePathsbasicCostCurrentChange"
              :current-page="disePathsPage"
              :page-sizes="[5, 10, 20, 50, 100, 200, 300, 400]"
              :page-size="disePathsSize"
              layout="total, sizes, prev, pager, next, jumper"
              :total="disePaths.length"
            >
            </el-pagination>
          </div>
        </el-tab-pane> -->
        <!-- <el-tab-pane label="基础项目费用" name="basicCost">
          <el-table
            :data="
              patBasicCost.slice(
                (patBasicCostPage - 1) * patBasicCostSize,
                patBasicCostPage * patBasicCostSize
              )
            "
            show-summary
            :summary-method="patBasicCostSummaries"
            style="width: 100%"
          >
            <el-table-column prop="费用类别" label="费用类别" width="180">
            </el-table-column>
            <el-table-column prop="项目名称" label="项目名称">
            </el-table-column>
            <el-table-column prop="标准单价" label="标准单价">
            </el-table-column>
            <el-table-column prop="数量" label="数量"> </el-table-column>
            <el-table-column prop="金额" label="金额"> </el-table-column>
          </el-table>

          <div class="block">
            <el-pagination
              @size-change="basicCostHandleSizeChange"
              @current-change="basicCostCurrentChange"
              :current-page="patBasicCostPage"
              :page-sizes="[5, 10, 20, 50, 100, 200, 300, 400]"
              :page-size="patBasicCostSize"
              layout="total, sizes, prev, pager, next, jumper"
              :total="patBasicCost.length"
            >
            </el-pagination>
          </div>
        </el-tab-pane> -->
        <el-tab-pane label="生成说明" name="generDesc">
          <pre style="color: red">
            <span style="font-size:20px;font-weight:bold;">生成说明：</span>
            ★ 自动生成：项目分类（药品、检验、检查提特征费用所有；其他内容提该病例项目，不显示基础项目）、项目小分类、非药品的治疗日期、费用小计    
            ★ 可以添加项目，如果添加的项目，是“基础项目”，则提示：当前添加项目，已经预设为基础项目，添加失败！    
            ★ 必须做的“项目小分类”打勾标记；如果多个项目小分类一起打勾必用，表示实际中，这几个项目小分类，至少且只能执行一种    
            ★ 做手术的病人，要把手术日标记出来，住院天数可以删除或增加    
            ★ 费用小计可以人工改（因为可以新增加项目）    
            ★ 做手术的病人，要把手术日标记出来，住院天数可以删除或增加    
            ★ 系统生成的蓝色单元格，是项目的处方日期    
            ★ 提前测算单个药品日均消耗金额，增加药品时候，方便测算费用；也要测算当前病例基础项目每天的花费，删除天数的时候，好适当扣减费用    
            ★ 在评价中，如果实际用了中草药，则项目小分类叫做中草药，名称把这些草药罗列出来，每一种逗号隔开；    
            ★ “费用小计”已经归集了“基础项目”的钱    
            ★ 药品，科室主任勾选的，是最合理的，没有勾选的同类，可能是不太合理的，但是不算做违规。所以多一个分类叫做“非最佳选择”    
            ★ 手术病人（分组是手术组），把手术用的麻醉、止痛、止血、预防用抗菌药物等，初始化到页面上，让科主任删减；备注“手术用”    
            ★ 特征费用中，“手术必用”药品，把药品用途，当作项目小分类写出来，放一起    
            ★★ 按：主要诊断+分组（入组的前面三位），来制定和维护路径模板，例如肱骨骨折，常见入组有IF1 IS2 
            </pre>
        </el-tab-pane>
      </el-tabs>
    </el-row>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import { HotTable, HotColumn } from "@handsontable/vue";
import { registerAllModules } from "handsontable/registry";
import { getLanguagesDictionaries } from "handsontable/i18n";
import { ContextMenu } from "handsontable/plugins/contextMenu";
import "handsontable/dist/handsontable.full.css";
import { MergeCells } from "handsontable/plugins";
import { HotTableComponent } from "@handsontable/vue/types";

import {
  pcbyid,
  getProType,
  pro2cost,
  autoProType,
  saveTpl,
  autoName
} from "@/api/commonApi";
import { Message, MessageBox, Row } from "element-ui";

import { proc4cost, findProTypeAndNameByPatId } from "@/api/patient";
import {
  tplExists,
  GetTplById,
  DisePath,
  stdCost,
  ljdir,
  ljVersion,
  ljCheckVersion,
  delTpls
} from "@/api/pathway";
import Handsontable from "handsontable";
import {
  cost,
  dec,
  opt,
  patientLs,
  patientinfo,
  getProTypeByPatId,
  patBasicCostById
} from "@/api/patient";
import { info, objectEach } from "handsontable/helpers";
import { rm } from "fs/promises";
import { setInterval, setTimeout } from "timers";
import { prototype } from "events";
import { Console } from "console";
import { getVersionName, getXVersionName } from "@/utils/Utils";
import { lstat } from "fs";
import { AxiosPromise } from "axios";
import { UserModule } from "@/store/modules/user";
registerAllModules();
@Component({
  name: "designer",
  components: { HotTable, HotColumn }
})
export default class extends Vue {
  private activeName: string = "basicInfo";

  //要自动合并的列名
  private mergeCols: Array<string> = ["项目分类", "项目小分类"];
  //默认有多少天
  private defaultDays: Array<{}> = [];

  private hotSettings = {
    // colWidths: 100,
    width: "auto",
    //设置合适高度
    height: `${document.body.clientHeight * 0.8}px`,
    rowHeaders: true,
    // colHeaders: true,
    rowHeights: 30,
    formulas: true,
    //language: "zh-CN",
    //minSpareRows: 1,
    //启动移动行
    manualRowMove: true,
    afterRowMove: (
      movedRows: [],
      finalIndex: number,
      dropIndex: number,
      movePossible: boolean,
      orderChanged: boolean
    ) => {
      this.afterRowMoveCallBack(
        movedRows,
        finalIndex,
        dropIndex,
        movePossible,
        orderChanged
      );
      //console.log(movedRows,finalIndex,dropIndex,movePossible,orderChanged)
    },
    // //顺序持久
    // persistentState: true,
    autoColumnSize: true,
    manualColumnResize: true,
    beforeKeyDown: (e: any) => {
      if (e.code == "Delete") {
        Handsontable.dom.stopImmediatePropagation(e);
        let hotInstance: Handsontable = (<any>this.$refs.hotTableComponent)
          .hotInstance;
        if (hotInstance.getSelectedLast()) {
          let r: any = hotInstance.getSelectedLast();
          this.contextMenu_click(
            "removerow",
            [
              {
                start: { col: r[1], row: r[0] },
                end: { col: r[3], row: r[2] }
              }
            ],
            e
          );
        }
      }
    },

    fillHandle: {
      //direction: "horizontal",
      autoInsertRow: false
    },
    // fillHandle: true,
    fixedColumnsLeft: 3,
    renderer: (
      instance: any,
      td: HTMLElement,
      row: any,
      col: any,
      prop: any,
      value: any,
      cellProperties: any
    ) => {
      let tr = td.parentNode;
      if (prop.startsWith("day")) {
        console.log(prop);
      }
      if (tr) {
        this.hot_renderer(instance, td, row, col, prop, value, cellProperties);
      }
    },
    // fixedColumnsRight: 1,
    afterChange: (changes: Array<any>, source: String) => {
      if ("MergeCells" == source) {
        return;
      }

      if (!changes) return;

      changes = changes[0];
      let col = changes[1];
      let oldVal: any = changes[2];
      let newVal: any = changes[3];
      let row = changes[0];

      //天数的值发生了变化
      if (col.startsWith("days")) {
        return;
        if (newVal != oldVal) {
          this.费用小计合并();
        }
      } else if ((col == "name" || col == "proSubType") && newVal) {
        newVal = newVal.split(" ")[0];
        this.afterChangeName(row, col, newVal);
      }
    },
    cells: (row: number, column: number, prop: string) => {
      return this.readonlyCell(row, column, prop);
    },
    comments: true,
    afterRender: () => {},
    className: "htCenter htMiddle",
    licenseKey: (<any>window)["MyConf"].HotTableLicenseKey,
    mergeCells: true,
    //表头菜单
    dropdownMenu: {
      callback: (key: any, selection: any, clickEvent: any) => {
        this.contextMenu_click(key, selection, clickEvent);
      },
      items: {
        delCol: {
          name: "删除天数",
          disabled: () => {
            return this.dropdownMenuDisable();
          }
        },
        addColLeft: {
          name: "增加天数（左）",
          disabled: () => {
            return this.dropdownMenuDisable();
          }
        },
        addColRight: {
          name: "增加天数（右）",
          disabled: () => {
            return this.dropdownMenuDisable();
          }
        }
      }
    },

    contextMenu: {
      callback: (key: any, selection: any, clickEvent: any) => {
        this.contextMenu_click(key, selection, clickEvent);
      },
      items: {
        row_above: {
          name: "插入一行（上）"
        },
        row_below: {
          name: "插入一行（下）"
        },
        separator: ContextMenu.SEPARATOR,
        mergeCells: {
          name: "（取消）合并单元格"
        },

        removerow: {
          name: "删除行"
        },
        goback: {
          name: "返回"
        },
        saveData: {
          name: "保存"
        }
      }
    }
  };
  //移动行之后保持数据的顺序
  private afterRowMoveCallBack(
    movedRows: Array<number>,
    finalIndex: number,
    dropIndex: number,
    movePossible: boolean,
    orderChanged: boolean
  ) {
    if (!orderChanged) return;

    let hotInstance: Handsontable = (<any>this.$refs.hotTableComponent)
      .hotInstance;

    //let [proType, proSubType] = hotInstance.getData()[movedRows[0]];

    this.resetData();

    hotInstance.getData().forEach((arr: Array<string>, index: number) => {
      let val = arr[2] || arr[1] || arr[0];
      let ts = this.data.filter(
        (it: any) => it.name == val || it.proSubType == val
      );
      if (ts.length > 0) ts[0].xh = index + 1;
    });
    this.重设数据源(this.data);

    setTimeout(() => {
      this.autoMergeRows(this.mergeCols, null);
    }, 100);
  }

  private readonlyCellTimer: any;

  //对行生成相关样式
  private hot_renderer(
    instance: any,
    td: HTMLElement,
    row: any,
    col: any,
    prop: any,
    value: any,
    cellProperties: any
  ) {
    Handsontable.renderers.TextRenderer.apply(this, <any>arguments);
    let tr = td.parentElement;
    if (!tr) return;

    let sValue = this.data[row].proSubType || this.data[row].name;
    if (prop == "proType" && sValue) {
      let tmpLs = this.allProjects.filter((it: any) => {
        return it.proSubType == sValue || it.name == sValue;
      });

      tr.className = tmpLs.length > 0 ? "lexits" : "";
    }
  }
  /**
   * 除药品外，其他“名称”字段设为只读
   */
  private readonlyCell(row: number, col: number, prop: any) {
    let cellProperties: any = {
      readOnly: true
    };
    if (!this.data[row]) return;
    let xmeno: any = this.data[row].xmeno;

    var types = ["药品", "医用材料"];

    //新增的一行
    if (
      !this.data[row].proType &&
      !this.data[row].proSubType &&
      !this.data[row].name
    ) {
      return;
    }

    //设置提示
    //1.如果项目小分类：名称字段为空，就设置小分类上
    if (prop == "proSubType") {
      if (!this.data[row].name) {
        cellProperties.comment = {
          value: xmeno,
          readOnly: false
        };
      }
    } else if (prop == "name") {
      cellProperties.comment = {
        value: xmeno,
        readOnly: false
      };
    }

    //"药品", "医用材料" 名称为可写,项目小分类为只读；其他名称为只读，项目小分类为可写
    //1.获取当前行的大类
    let proType = "";
    let row0 = row;
    do {
      proType = this.data[row0--].proType;
    } while (!proType);

    //"药品", "医用材料" 名称为可写,项目小分类为只读；其他名称为只读，项目小分类为可写
    if (types.includes(proType)) {
      if (prop == "proSubType") {
        return cellProperties;
      } else if (prop == "name") {
        cellProperties.readOnly = false;
        return cellProperties;
      }
    }
    //其他名称和大分类不可写
    if (prop == "name" || prop == "proType") {
      return cellProperties;
    }

    cellProperties.readOnly = false;
    return cellProperties;

    // let o: any = this.getSectionByProType(["药品", "医用材料"]);

    // //药口和医用材料名称为可写

    // var types = ["药品", "医用材料"];

    // let keys = Object.keys(o);

    // for (let i = 0; i < keys.length; i++) {
    //   let start: number = o[keys[i]].start;
    //   let end: number = o[keys[i]].end;
    //   if (row >= start && row <= end) {
    //     if (prop == "proSubType") {
    //       return cellProperties;
    //     }
    //     if (prop == "name") {
    //       var p: any = { readOnly: false };
    //       var xmeno = this.data[row].xmeno;
    //       if (xmeno) {
    //         p.comment = { value: xmeno, readOnly: false };
    //       }
    //       return p;
    //     }
    //   }
    // }

    // if (prop == "proSubType" && !this.data[row]?.name) {
    //   var p: any = { readOnly: true };
    //   var xmeno = this.data[row]?.xmeno;
    //   if (xmeno) {
    //     p.comment = { value: xmeno, readOnly: true };
    //   }
    //   return p;
    // }

    // if (prop == "name") return cellProperties;
  }
  private getSectionByProType(proTypes: Array<string>) {
    let o: any = {};

    let ls: [] = this.data.filter((it: any) => proTypes.includes(it.proType));

    for (let i = 0; i < ls.length; i++) {
      let it: any = ls[i];
      let j = this.data.indexOf(it);
      o[it.proType] = { start: j };
      j++;
      if (j < this.data.length) {
        for (; j < this.data.length; j++) {
          if (this.data[j].proType) {
            break;
          }
          o[it.proType].end = j;
        }
      } else {
        o[it.proType].end = o[it.proType].start;
      }
    }
    return o;
  }

  private afterChangeTimer: any = 0;

  //做超20%以上红色，不足80%蓝色，剩余的黑色
  private costChangeCss(val1: number, val2: number) {
    if (val1 == 0) return "";

    let f = val1 / val2;

    return { costColorRed: f > 1.2, costColorBlue: f < 0.8 };
  }
  /**
   * 总计值发生变化时触发
   */
  private totalObj: any = { cost: 0 };
  // private totalChangeTimer: any;
  // private totalChange() {

  //   if (this.totalChangeTimer) {
  //     clearTimeout(this.totalChangeTimer);
  //   }

  //   this.totalChangeTimer = setTimeout(() => {
  //     this.totalObj = { cost: 0 };
  //     let vals = this.data.filter((it: any) => it.proType);
  //     vals.forEach((v: any) => {
  //       this.totalObj[v.proType] = v.total ? v.total : 0;
  //       this.totalObj.cost += this.totalObj[v.proType];
  //     });
  //     console.log(vals,this.totalObj);
  //   }, 200);
  // }

  private priceObjCache: any = {};
  /**
   * 根据大类计算费用小计
   */
  private getSum(大类: string) {
    // console.log(this.costInfo.costs);

    let start = 0;
    for (let i = 0; i < this.data.length; i++) {
      if (this.data[i].proType == 大类) {
        start = i;
        break;
      }
    }
    let sum = 0;

    let hotInstance: Handsontable = (<any>this.$refs.hotTableComponent)
      .hotInstance;

    let dayCols: any = hotInstance.getSettings().columns;
    dayCols = dayCols.filter((d: any) => d.data.startsWith("days"));
    //console.log(dayCols,this.路径项目天数费用参考缓存);
    for (let i = start; i < this.data.length; i++) {
      if (this.data[i].proType && this.data[i].proType != 大类) break;

      let proName = this.data[i].name;
      if (!proName) continue;

      for (let j = 0; j < dayCols.length; j++) {
        let r = /days(\d+)/;
        let col = dayCols[j].data;
        let vals: any = r.exec(col);
        let day = vals[1];
        day = parseInt(day);

        // let prices=this.costInfo.costs.filter((it:any)=>it.name==this.costInfo.costs);
        // if(prices.length==0) continue;
        if (this.data[i][col] && this.priceObjCache[proName]) {
          sum += this.priceObjCache[proName];
        }
        // if (!this.路径项目天数费用参考缓存[proName]) continue;

        // if (this.data[i][col] && this.路径项目天数费用参考缓存[proName]) {
        //   let amount = this.路径项目天数费用参考缓存[proName].amount;
        //   if (amount) sum += amount;
        // }
      }
    }
    return sum;
  }
  /**
   * 获取非药品大类费用信息
   */
  private getSum4notMedic(proType: string) {
    let start = 0;
    for (let i = 0; i < this.data.length; i++) {
      if (this.data[i].proType == proType) {
        start = i;
        break;
      }
    }
    let sum = 0;

    let hotInstance: Handsontable = (<any>this.$refs.hotTableComponent)
      .hotInstance;

    let dayCols: any = hotInstance.getSettings().columns;
    dayCols = dayCols.filter((d: any) => d.data.startsWith("days"));
    //console.log(dayCols,this.路径项目天数费用参考缓存);

    this.resetData();
    let ls = this.data.filter((it: any) => it.proType == proType);

    ls.forEach((it: any) => {
      for (let j = 0; j < dayCols.length; j++) {
        let r = /days(\d+)/;
        let col = dayCols[j].data;
        let vals: any = r.exec(col);
        let day = vals[1];
        day = parseInt(day);
        if (it[col]) {
          let tmpPrice = 0;
          let cost = this.costInfo.cost4days.filter((c: any) => {
            return (
              c.proType == it.proType &&
              c.proSubType == it.proSubType &&
              c.ts == day
            );
          });
          // if (it.proSubType == "感染四项") {
          //   console.log(it.proSubType, JSON.stringify(cost));
          // }
          if (cost.length > 0) {
            tmpPrice = cost[0].amount;
            sum += cost[0].amount;
          } else {
            cost = this.costInfo.costs.filter(
              (it: any) =>
                it.proType == it.proType && it.proSubType == it.proSubType
            );
            // if (it.proSubType == "感染四项") {
            //   console.log(it.proSubType, JSON.stringify(cost));
            // }
            if (cost.length > 0) {
              tmpPrice = cost[0].price;
              sum += cost[0].price;
            }
          }
        }
      }
    });
    // let tmpProType: string = "";
    // let tmpProSubType: string = "";

    // for (let i = start; i < this.data.length; i++) {
    //   if (this.data[i].proType && this.data[i].proType != proType) break;

    //   if (!tmpProType) tmpProType = this.data[i].proType;
    //   if (this.data[i].proSubType) tmpProSubType = this.data[i].proSubType;

    //   for (let j = 0; j < dayCols.length; j++) {
    //     let r = /days(\d+)/;
    //     let col = dayCols[j].data;
    //     let vals: any = r.exec(col);
    //     let day = vals[1];
    //     day = parseInt(day);

    //     if (this.data[i][col]) {
    //       let tmpPrice = 0;
    //       let cost = this.costInfo.cost4days.filter(
    //         (it: any) =>
    //           it.proType == tmpProType &&
    //           it.proSubType == tmpProSubType &&
    //           it.ts == day
    //       );
    //       // if (tmpProType == "手术") console.log("i", i, this.data[i][col],cost);
    //       if (cost.length > 0) {
    //         tmpPrice = cost[0].amount;
    //         sum += cost[0].amount;
    //       } else {
    //         cost = this.costInfo.costs.filter(
    //           (it: any) =>
    //             it.proType == tmpProType && it.proSubType == tmpProSubType
    //         );
    //         if (cost.length > 0) {
    //           tmpPrice = cost[0].price;
    //           sum += cost[0].price;
    //         }
    //       }
    //     }
    //   }
    // }
    return sum;
  }

  // private 路径项目天数费用参考缓存: any = {};

  // /**
  //  * proSubType修改的处理方法
  //  */
  // private async changeProSubType(row: number, col: string, val: string) {
  //   var vals = this.autoProTypeData.filter((it: any) => it.proSubType == val);
  //   if (vals.length == 0) return;
  //   vals = vals[0];
  //   let hotInstance: Handsontable = (<any>this.$refs.hotTableComponent)
  //     .hotInstance;
  //   if (vals.属性 == 1) {
  //     //如果是基础项目就提示
  //     Message({
  //       message: "当前添加项目，已经预设为基础项目，添加失败！",
  //       type: "error",
  //       duration: 5 * 1000,
  //     });
  //     this.data[row][col] = "";
  //     hotInstance.setDataAtRowProp(row, "name", "");
  //     return;
  //   }
  // }
  /**
   * 字段"name"修改好的处理方法
   */

  private comparseigorncase(a: string, b: string) {
    a = (a || "").toLocaleLowerCase();
    b = (b || "").toLocaleLowerCase();
    return a == b;
  }
  private async afterChangeName(row: number, col: string, val: string) {
    val = val.toLocaleLowerCase();

    this.插入一行 = false;
    // this.autoNameData.forEach((it: any) => {
    //   if (it.名称) it.名称 = it.名称.toLocaleLowerCase();
    //   if (it.说明) it.说明 = it.说明.toLocaleLowerCase();

    //   it.拼音简码 = it.拼音简码.toLocaleLowerCase();
    // });
    var vals = this.autoNameData.filter((it: any) => {
      return (
        this.comparseigorncase(it.名称, val) ||
        this.comparseigorncase(it.拼音简码, val)
      );
    });

    if (col == "proSubType") {
      vals = this.autoNameData.filter((it: any) => {
        return (
          this.comparseigorncase(it.说明, val) ||
          this.comparseigorncase(it.拼音简码, val)
        );
      });
    }

    if (vals.length == 0) {
      vals = this.autoNameData.filter((it: any) => {
        return (
          it.名称.startsWith(val) ||
          it.说明.startsWith(val) ||
          it.拼音简码.startsWith(val)
        );
      });
    }

    let hotInstance: Handsontable = (<any>this.$refs.hotTableComponent)
      .hotInstance;

    if (vals.length == 0) {
      this.data[row][col] = "";
      hotInstance.render();
      return;
    }

    vals = vals[0];

    if (vals.属性 == 1) {
      //如果是基础项目就提示
      Message({
        message: "当前添加项目，已经预设为基础项目，添加失败！",
        type: "error",
        duration: 5 * 1000
      });
      this.data[row][col] = "";
      //hotInstance.setDataAtRowProp(row, col, "");
      return;
    }
    let mycol = col == "name" ? "名称" : "说明";
    val = vals[mycol];

    this.data[row][col] = val;
    var obj: any = {
      proType: vals.类型A,
      proSubType: vals.说明,
      mark: vals.属性 == "2" ? "不判断" : "",
      xmeno: vals.xmeno
    };
    //项目ID
    let pcode = vals.ID;

    Object.keys(obj).forEach((k: string) => {
      //hotInstance.setDataAtRowProp(row, k, obj[k]);
      this.data[row][k] = obj[k];
    });
    this.data[row].xh = row + 1;
    hotInstance.render();

    let mergeCellIntance: MergeCells = hotInstance.getPlugin("mergeCells");
    //先取消再合并
    //TODO:没有其他办法处理此BUG?
    this.autoMergeRows(this.mergeCols, null, null);
  }
  private data: any = [];

  //删除、增加天数
  private dropdownMenuDisable() {
    let hotInstance: Handsontable = (<any>this.$refs.hotTableComponent)
      .hotInstance;

    let col: any = hotInstance.getSelected();
    let scol: any = col[0][1];
    col = col[0][0];
    scol = hotInstance.getColHeader()[scol];
    return !/第\d+天/.test(scol);
  }

  private mergeRowsCache: Array<any> = [];
  /**
   * 自动合并单元格
   * @param cols 要合并的列
   * @param depends 依赖列
   */
  private autoMergeRows(
    cols: Array<string>,
    depends: Array<string> | null,
    ignoreRow: number | null = null
  ) {
    //1.获取当前表格实例

    this.mergeRowsCache = [];

    console.log("...autoMergeRows...");
    let hotInstance: Handsontable = (<any>this.$refs.hotTableComponent)
      .hotInstance;

    let mergeCellIntance: MergeCells = hotInstance.getPlugin("mergeCells");
    //先取消再合并
    //TODO:没有其他办法处理此BUG?
    mergeCellIntance.unmerge(0, 0, 10000, 1);

    // hotInstance.render();

    //2.获取表头行
    let tbheaders: Array<string> = <Array<string>>hotInstance.getColHeader();

    //3.获取要合并、依赖项所在列的下标
    let colsIndexs: Array<number> = cols
      .map(it => tbheaders.indexOf(it))
      .filter(it => it > -1);

    //TODO:暂时不用
    let dependsIndexs: Array<number> = [];
    if (depends) {
      dependsIndexs = depends
        .map(it => tbheaders.indexOf(it))
        .filter(it => it > -1);
    }
    var colMap: any = { 项目分类: "proType", 项目小分类: "proSubType" };

    // let hotData = hotInstance.getData();

    //解决合并后值为NULL的情况

    let preProType = "",
      preProSubType = "";

    for (let i = 0; i < this.data.length; i++) {
      if (ignoreRow && ignoreRow == i) {
        continue;
      }
      if (this.data[i].proType) {
        preProType = this.data[i].proType;
      }

      if (this.data[i].proSubType) {
        preProSubType = this.data[i].proSubType;
      }
      if (!this.data[i].proType) this.data[i].proType = preProType;
      if (!this.data[i].proSubType) this.data[i].proSubType = preProSubType;
    }
    let columns: Array<any> = <any>hotInstance.getSettings().columns;
    //4.合并
    for (let j = cols.length - 1; j >= 0; j--) {
      let start: any = null;
      let end: any = null;

      for (let i = 1; i < this.data.length; i++) {
        let pre: any = this.data[i - 1];
        let cur: any = this.data[i];

        let colName = colMap[cols[j]];
        let curColIndex = columns.indexOf(
          columns.filter(c => c.data == colName)[0]
        );

        if (pre[colName] == cur[colName]) {
          if (!start) {
            start = { row: i - 1, col: curColIndex };
          }
          end = { row: i, col: curColIndex };
        } else {
          if (start) {
            this.mergeCells(start, end);
          }
          start = null;
          end = null;
        }
      }

      if (start) {
        this.mergeCells(start, end);
      }
    }

    let rqdMergeCellLs: any = [];
    Object.keys(this.rqdMergeCells).forEach((k: any) => {
      rqdMergeCellLs.push(this.rqdMergeCells[k]);
    });

    if (rqdMergeCellLs.length > 0) {
      for (let j = 0; j < rqdMergeCellLs.length; j++) {
        this.mergeCells(rqdMergeCellLs[j].start, rqdMergeCellLs[j].end);
      }
    }

    hotInstance.render();
    // this.费用小计合并();

    // //TODO:解决小计不更新问题
    // let f = (t: number) => {
    //   if (t <= 2) {
    //     setTimeout(() => {
    //       this.费用小计合并();
    //       hotInstance.render();
    //     }, 200);
    //     f(t + 1);
    //   }
    // };
    // f(1);
  }

  /**
   * 合并单元格
   */
  private mergeCells(
    start: { row: number; col: number },
    end: { row: number; col: number }
  ) {
    let hotInstance: Handsontable = (<any>this.$refs.hotTableComponent)
      .hotInstance;
    let mergeCellIntance: MergeCells = hotInstance.getPlugin("mergeCells");

    mergeCellIntance.merge(start.row, start.col, end.row, end.col);

    this.mergeRowsCache.push({ start: start, end: end });
    //hotInstance.render();
  }

  //小计合并及赋值 药品
  private 费用小计合并() {
    console.log("....费用小计合并....");

    let hotInstance: Handsontable = (<any>this.$refs.hotTableComponent)
      .hotInstance;
    let cols: any = hotInstance.getSettings().columns;
    if (!cols) return;
    let totalIndex = cols.findIndex((it: any) => it.data == "total");

    let grpIndexes = this.data
      .filter((it: any) => it.proType)
      .map((it: any) => this.data.indexOf(it));

    for (let i = 0; i < grpIndexes.length; i++) {
      let curIndex = grpIndexes[i];

      let startRow = grpIndexes[i];
      let endRow = grpIndexes[i + 1] - 1;
      if (isNaN(endRow)) endRow = this.data.length - 1;
      this.mergeCells(
        { row: startRow, col: totalIndex },
        { row: endRow, col: totalIndex }
      );
      //药品计算费用
      let sum = 0;
      if (this.data[curIndex].proType == "药品") {
        sum = this.getSum(this.data[curIndex].proType);
        this.data[curIndex].total = sum == 0 ? "" : sum.toFixed(2);
      } else {
        sum = this.getSum4notMedic(this.data[curIndex].proType);
        this.data[curIndex].total = sum == 0 ? "" : sum.toFixed(2);
      }

      // hotInstance.setDataAtRowProp(curIndex, "total",  this.data[curIndex].total,'tt');
      this.totalObj[this.data[curIndex].proType] = parseFloat(
        this.data[curIndex].total
      );
    }

    this.totalObj.cost = 0;
    Object.keys(this.totalObj).forEach((k: string) => {
      if (k !== "cost") {
        if (this.totalObj[k]) this.totalObj.cost += this.totalObj[k];
      }
    });

    setTimeout(() => {
      this.totalObj = JSON.parse(JSON.stringify(this.totalObj));
      hotInstance.render();
    }, 100);
  }

  private 插入一行: boolean = false;

  private rqdMergeCells: any = {};
  //单元格下拉菜单事件
  private contextMenu_click(key: string, selection: any, clickEvent: any) {
    let hotInstance: Handsontable = (<any>this.$refs.hotTableComponent)
      .hotInstance;
    let colOps = ["delCol", "addColLeft", "addColRight"];

    let columns: any = hotInstance.getSettings().columns;

    this.插入一行 = key.startsWith("row_");

    if (key == "saveData") {
      this.save();
      return;
    }

    //记录必选项，合并项
    if (key == "mergeCells") {
      //let cellCol = selection.start.col;
      selection = selection[0];
      if (
        columns.length + 1 >= selection.start.col &&
        columns[selection.start.col].data == "rqd"
      ) {
        let k = `${selection.start.row}${selection.start.col}${selection.end.row}${selection.end.col}`;

        //如果有值，代表之前已经合并过啦，这时是取消合并。如果没有值，这代表合并。
        if (this.rqdMergeCells[k]) {
          delete this.rqdMergeCells[k];
          console.log("取消合并", k);
        } else {
          this.rqdMergeCells[k] = selection;
        }
      }

      return;
    }

    //删除、增加天数
    if (colOps.includes(key)) {
      let col: any = hotInstance.getSelected();
      let scol: any = col[0][1];
      scol = hotInstance.getColHeader()[scol];
      //获取正在操作的“天数”
      let r = /第(\d+)天/;
      let day: any = r.exec(scol);
      day = parseInt(day[1]);
      let columns: any = hotInstance.getSettings().columns;
      columns = columns.filter((it: any) => it.data.startsWith("days"));
      let endDays = Math.max(
        ...columns.map((it: any) => {
          let curDay: any = /days(\d+)/.exec(it.data);
          return parseInt(curDay[1]);
        })
      );
      //删除天数
      if (key === "delCol") {
        //将“第一天换成第二天的值”
        this.顺延天数(day, endDays);
        //删除带有“天数”的费用元数据
        this.costInfo.cost4days = this.costInfo.cost4days.filter(
          (it: any) => it.ts !== day
        );

        //删除最后一天
        for (let j = 0; j < this.data.length; j++) {
          delete this.data[`days${endDays}`];
        }

        this.重设天数(columns.length - 1);
      }
      //在左边增加行
      if (key === "addColLeft") {
        //let isRight=key=='addColRight'?true:false;
        this.顺延天数(day, endDays + 1, true);
        for (let j = 0; j < this.data.length; j++) {
          //清空当前天数的值
          this.data[j][`days${day}`] = null;
        }
        this.重设天数(columns.length + 1);
      }
      //在右边增加
      if (key === "addColRight") {
        this.顺延天数(day + 1, endDays + 1, true);

        for (let j = 0; j < this.data.length; j++) {
          //清空当前天数的值
          this.data[j][`days${day + 1}`] = null;
        }
        this.重设天数(columns.length + 1);
      }

      this.重设数据源(this.data);
    }

    //删除行
    if (key == "removerow") {
      let sn = selection[0];
      let startRow = sn.start.row;

      //删除的是小分类的第一个,解决合并没大项的可能 开始
      let proType = "";
      for (let i = sn.start.row; i <= sn.end.row; i++) {
        if (this.data[i].proType) {
          proType = this.data[i].proType;
        }
      }

      if (proType) {
        for (let i = sn.end.row + 1; i < this.data.length; i++) {
          if (!this.data[i].proType) {
            this.data[i].proType = proType;
          } else break;
        }
      }

      //结束

      hotInstance.alter(
        "remove_row",
        sn.start.row,
        sn.end.row - sn.start.row + 1
      );

      this.重设数据源(this.data);
    }

    if (key == "goback") {
      this.$router.go(-1);
      // let u = "/clinicalpathway/user";
      // if (this.$route.query.tid) {
      //   u = "/clinicalpathway/template";
      // }
      // this.$router.push({
      //   path: u,
      // });
    }
    if (key == "delCol" || key == "removerow" || key.startsWith("addCol")) {
      setTimeout(() => {
        this.autoMergeRows(this.mergeCols, null);
      }, 100);
    }
  }

  /**
   * 调整天数
   * @param startDay 开始天数
   * @param endDay 结束天数
   * @param reverse TRUE|FALSE TRUE:从后往前调整，FALSE：从前往后调整
   */
  private 顺延天数(startDay: number, endDay: number, reverse: boolean = false) {
    //在左边添加行或右边添加行，将”费用天数“作相应的改变
    if (reverse) {
      for (let j = 0; j < this.costInfo.cost4days.length; j++) {
        if (this.costInfo.cost4days[j].ts >= startDay) {
          this.costInfo.cost4days[j].ts++;
        }
      }
    }
    //删除列时，删除相关的“费用天数”信息
    if (!reverse) {
      //1.删除当前天的相关“费用天数”信息
      let rmLs = this.costInfo.cost4days.filter((it: any) => it.ts == startDay);
      for (let j = 0; j < rmLs.length; j++) {
        this.costInfo.cost4days.slice(
          this.costInfo.cost4days.indexOf(rmLs[j]),
          1
        );
      }
      //2.对后面的天数，每个减1天。
      this.costInfo.cost4days
        .filter((it: any) => it.ts > startDay)
        .forEach((it: any) => {
          it.ts--;
        });
    }
    if (!reverse) {
      for (let i = startDay; i < endDay; i++) {
        for (let j = 0; j < this.data.length; j++) {
          this.data[j]["days" + i] = this.data[j]["days" + (i + 1)];
        }
      }
    } else {
      for (let i = endDay; i > startDay; i--) {
        for (let j = 0; j < this.data.length; j++) {
          this.data[j]["days" + i] = this.data[j]["days" + (i - 1)];
        }
      }
    }
  }
  //重新设置数据
  private resetData() {
    //项目分类、项目小分类、合并后为空问题解决

    let tmpProType: string = "";
    let tmpProSubType: string = "";
    let tmpRqd = null;

    for (let i = 0; i < this.data.length; i++) {
      if (this.data[i].proType) tmpProType = this.data[i].proType;
      if (this.data[i].proSubType) tmpProSubType = this.data[i].proSubType;
      if (!this.data[i].proType) this.data[i].proType = tmpProType;
      if (!this.data[i].proSubType) this.data[i].proSubType = tmpProSubType;
      if (this.data[i].rqd != null) tmpRqd = this.data[i].rqd;

      if (this.data[i].rqd == null) {
        this.data[i].rqd = tmpRqd;
      }
    }
  }

  /**
   * 检查当前路径信息有没有被其他模板使用，如果使用了，就弹出替换或保存的框框
   */
  private async 检查路径版本() {
    let d: any = await ljCheckVersion({
      pid: this.patwayinfo.ID,
      t: this.patwayinfo.场合
    });

    d = d.data;

    if (d && d.length > 0) {
      if (this.docId) {
        let ff = d.filter((it: any) => it.ID !== this.docId);
        if (ff.length > 0) {
          return { m: true, id: ff.map((it: any) => it.ID).join(",") };
        } else {
          return { m: false };
        }
      }
      return { m: true, id: d.map((it: any) => it.ID).join(",") };
    }
    return { m: false };
  }
  private 重设数据源(data: Array<any>) {
    let hotInstance: Handsontable = (<any>this.$refs.hotTableComponent)
      .hotInstance;
    this.data = data;

    this.数据排序();

    hotInstance.loadData(this.data);
  }
  private 数据排序() {
    let colMap: any = { 药品: 1, 检验: 2, 检查: 3, 治疗: 4 };
    this.data.sort((a: any, b: any) => {
      let xh1 = a.xh;
      let xh2 = b.xh;

      return xh1 - xh2;
    });
  }

  private hashcode(str: string) {
    str = str || "";
    var hash = 0;
    if (str.length == 0) return hash;
    for (let i = 0; i < str.length; i++) {
      let char = str.charCodeAt(i);
      hash = (hash << 5) - hash + char;
      hash = hash & hash; // Convert to 32bit integer
    }
    return Math.abs(hash);
  }
  private nameautocomplete: any = null;
  private autoNameData: any = null;
  private nameChangeTimer: any;
  // private autoProTypeData: any = null;
  // private autoProTypeTimer: any;

  private autoProSubTypeSource: any;

  private 重设天数(days: number) {
    let hotInstance: Handsontable = (<any>this.$refs.hotTableComponent)
      .hotInstance;

    let cols = [
      {
        title: "项目分类",
        data: "proType"
      },
      {
        title: "项目小分类",
        data: "proSubType",
        type: "autocomplete",
        source: (query: any, process: Function) => {
          // autoProType({ n: "" });

          let url = `${
            (<any>window).MyConf.APISERVICE
          }/api/auto-proType?n=${query}`;
          autoProType({ n: query }).then((rep: any) => {
            this.autoNameData = rep.data;
            this.autoNameData.forEach((it: any) => {
              it.拼音简码 = it.拼音简码.toLocaleLowerCase();
            });
            process([
              ...this.autoNameData.map((it: any) => it.说明 + " " + it.拼音简码)
            ]);
          });
          // fetch(url)
          //   .then((response) => response.json())
          //   .then((response) => {
          //     //console.log(response.data);
          //     this.autoNameData = response.data;
          //     this.autoNameData.forEach((it: any) => {
          //       it.拼音简码 = it.拼音简码.toLocaleLowerCase();
          //     });
          //     process([
          //       ...this.autoNameData.map(
          //         (it: any) => it.说明 + " " + it.拼音简码
          //       ),
          //     ]);
          //   });

          // this.autoNameData = this.autoProSubTypeSource;
          // this.autoNameData.forEach((it: any) => {
          //   it.拼音简码 = it.拼音简码.toLocaleLowerCase();
          // });
          // process(
          //   this.autoNameData.map((it: any) => it.名称 + " " + it.拼音简码)
          // );
        }
      },
      {
        title: "名称",
        data: "name",
        type: "autocomplete",
        source: (query: any, process: Function) => {
          let selectedLast: any = hotInstance.getSelectedLast();
          //查找大类、小分类
          let ls: Array<any> = hotInstance.getData();
          let row = selectedLast[0];
          let col = selectedLast[1] - 1;

          let proType = "";
          let proSubType = ls[row][col];
          for (let i = row; i >= 0; i--) {
            proType = ls[i][col - 1];
            //如果是合并滴单元格，就向前获取某个单元格的小分类
            if (!this.插入一行) {
              if (!proSubType) {
                proSubType = ls[i][col];
              }
            }
            if (proType) {
              break;
            }
          }

          proType = proType || "";
          proSubType = proSubType || "";
          let discode = !proSubType ? "" : this.discode;

          if (this.nameChangeTimer) clearTimeout(this.nameChangeTimer);

          this.nameChangeTimer = setTimeout(() => {
            //如果不是临床路径当中有的项目，就不带疾病编码
            if (proType != "医用材料") {
              if (
                this.allProjects.filter(
                  (it: any) => it.proSubType == proSubType
                ).length == 0
              ) {
                discode = "";
                //proSubType = "";
              }
            }

            var qp: any = {
              proType: proType,
              proSubType: proSubType,
              s: query
            };

            let fetchFun: any = autoName;
            // let url = `${
            //   (<any>window).MyConf.APISERVICE
            // }/api/auto-name?proType=${proType}&proSubType=${proSubType}&s=${query}`;
            if (discode) {
              //url += `&discode=${discode}`;
              qp.discode = discode;
              //fetchFun=autoName;
            }

            if (proType == "医用材料") {
              // url = `${
              //   (<any>window).MyConf.APISERVICE
              // }/api/auto-project?proType=${proType}&proSubType=${proSubType}&s=${query}`;
              qp = { proType: proType, proSubType: proSubType, s: query };
              //autoProType(qp);
              fetchFun = autoProType;
            }

            fetchFun(qp).then((rep: any) => {
              this.autoNameData = rep.data;
              this.autoNameData.forEach((it: any) => {
                it.拼音简码 = it.拼音简码.toLocaleLowerCase();
              });
              process([
                ...this.autoNameData.map(
                  (it: any) => it.名称 + " " + it.拼音简码
                )
              ]);
            });
            // fetch(url)
            //   .then((response) => response.json())
            //   .then((response) => {
            //     //console.log(response.data);
            //     this.autoNameData = response.data;
            //     this.autoNameData.forEach((it: any) => {
            //       it.拼音简码 = it.拼音简码.toLocaleLowerCase();
            //     });
            //     process([
            //       ...this.autoNameData.map(
            //         (it: any) => it.名称 + " " + it.拼音简码
            //       ),
            //     ]);
            //   });
          }, 300);
        },
        strict: false
      },
      {
        title: "必选项",
        data: "rqd",
        type: "checkbox",
        checkedTemplate: true,
        uncheckedTemplate: false
      },
      {
        title: "备注",
        data: "mark"
      }
      //动态生成天数
      // ...Array.from(new Array(days).keys()).map((it: number) => {
      //   let col: any = {
      //     title: `第${it + 1}天`,
      //     data: `days${it + 1}`,
      //     source: ["", "√"],
      //     type: "autocomplete",
      //     strict: true,
      //     class: "pansir",
      //     //type: "numeric",
      //     dropdownMenu: false,
      //   };

      //   if (it + 1 == this.userinfo.optDay) {
      //     col.title += "<div class='colheaderred'>手术日</div>";
      //   } else if (it == 0) {
      //     col.title += "<div class='colheaderred'>入院日</div>";
      //   } else if (it + 1 == days)
      //     col.title += "<div class='colheaderred'>出院日</div>";

      //   //col.renderer=this.dayrenderer;

      //   return col;
      // }),
      // {
      //   title: "费用小计",
      //   data: "total",
      //   type: "numeric",
      // },
    ];
    //更新配置
    hotInstance.updateSettings(
      {
        columns: cols
      },
      false
    );
  }

  private 是合并单元格(cell: { col: Number; row: number }) {
    for (let i = 0; i < this.mergeRowsCache.length; i++) {
      let m = this.mergeRowsCache[i];
      if (
        m.end.col == cell.col &&
        m.start.row <= cell.row &&
        cell.row <= m.end.row
      ) {
        return true;
      }
    }
    return false;
  }

  private docId: string = "";

  /**
   * 保存前检查
   */
  private beforeSave(rqdMergeCellsObj: any) {
    //1.合并了滴必须要勾选
    //console.log(rqdMergeCellsObj);

    if (Object.keys(rqdMergeCellsObj).length > 0) {
      // let rs = Object.keys(rqdMergeCellsObj)
      //   .filter((it: any) => {
      //     let ls = rqdMergeCellsObj[it];
      //     let len = this.data.filter((it2: any) => {
      //       let k = it2.name || it2.proSubType;
      //       return ls.includes(k) && it2.rqd == true;
      //     }).length;
      //     return ls.length != len;
      //   })
      //   .map((it: any) => {
      //     return rqdMergeCellsObj[it].join("、");
      //   });
      // if (rs.length > 0) {
      //   return `${rs.join("、")}合并未勾选`;
      // }
    }

    //2.药品：小分类相同，明细只勾选了部份不可以。

    let obj: any = {};
    this.data.forEach((it: any) => {
      obj[it.proSubType] = obj[it.proSubType] || [];
      obj[it.proSubType][it.rqd] = 1;
    });
    let ls = Object.keys(obj).filter((k: any) => {
      return Object.keys(obj[k]).length > 1;
    });
    if (ls.length > 0) {
      return `${ls.join("、")}不合理`;
    }

    //3.小分类有没有重复项
    let proSubTypes = Array.from(
      new Set(this.data.map((it: any) => it.proSubType))
    );
    for (let i = 0; i < proSubTypes.length; i++) {
      let p = proSubTypes[i];
      let ts = this.data.filter((it: any) => it.proSubType == p);
      if (ts.length > 1) {
        let min = Math.min(...ts.map((it: any) => it.xh));
        let max = Math.max(...ts.map((it: any) => it.xh));
        //console.log(min,max,ts[0].proSubType,ts)
        for (let m = min; m <= max; m++) {
          let tmpLs = ts.filter((it: any) => it.xh == m);
          if (tmpLs.length == 0) {
            return `'${p}'重复！`;
          }
        }
      }
    }
    return "";
  }
  private async save() {
    let hotInstance: Handsontable = (<any>this.$refs.hotTableComponent)
      .hotInstance;

    let cols: any = hotInstance.getSettings().columns;
    let days = cols.filter((it: any) => it.data.startsWith("days")).length;

    let tpl = this.curTpl || {
      id: this.docId,
      名称:
        this.userinfo.discode?.substring(0, 3) +
        " " +
        (this.userinfo.drgcode || "").substring(0, 3),
      天数: days,
      疾病编码: this.discode,
      疾病名称: this.userinfo.disname,
      分组编码: this.userinfo.drgcode,
      分组名称: this.userinfo.drgname,
      手术编码: this.userinfo.optcode,
      手术名称: this.userinfo.optname,
      路径ID: this.patwayinfo.ID,
      路径版本: this.patwayinfo.场合,
      费用: this.totalObj.cost,
      作者: UserModule.name,
      最近修改人: UserModule.name
    };

    tpl.路径ID = this.patwayinfo.ID;
    tpl.路径版本 = this.patwayinfo.场合;

    this.resetData();
    this.data.forEach((it: any, i: number) => {
      it.xh = i + 1;
      it.id = this.guid();
    });

    let saveAction = async () => {
      let formData = {
        tpl: tpl,
        metas: [
          {
            id: this.guid(),
            字段名称: "days",
            字段值: days,
            备注: "天数"
          },
          {
            id: this.guid(),
            字段名称: "discode",
            字段值: this.discode,
            备注: "疾病编码"
          },
          //this.costInfo.cost4days
          {
            id: this.guid(),
            字段名称: "cost4days",
            字段值: JSON.stringify(this.costInfo.cost4days),
            备注: "费用天数"
          }
          //this.rqdMergeCells
        ],

        data: this.data
      };
      Object.keys(this.totalObj).forEach((k: string) => {
        formData.metas.push({
          id: this.guid(),
          字段名称: k,
          字段值: this.totalObj[k],
          备注: "totalObj"
        });
      });
      Object.keys(this.userinfo).forEach((k: string) => {
        if (k !== "optDate") {
          formData.metas.push({
            id: this.guid(),
            字段名称: k,
            字段值: this.userinfo[k],
            备注: "userinfo"
          });
        }
      });
      let rqdMergeCellsObj: any = {};
      if (this.rqdMergeCells && Object.keys(this.rqdMergeCells)) {
        formData.metas.push({
          id: this.guid(),
          字段名称: "rqdMergeCells",
          字段值: JSON.stringify(this.rqdMergeCells),
          备注: "必选合并单元格"
        });
        let dd = hotInstance.getData();

        Object.keys(this.rqdMergeCells).forEach((k: string) => {
          let start = this.rqdMergeCells[k].start;
          let end = this.rqdMergeCells[k].end;
          let ls = [];

          for (let r = start.row; r <= end.row; r++) {
            let val = "";
            for (let i = start.col - 1; i >= 0; i--) {
              if (dd[r][i]) {
                val = dd[r][i];
                break;
              }
            }
            ls.push(val);
          }
          rqdMergeCellsObj[k] = ls;
        });
        Object.keys(rqdMergeCellsObj).forEach((k: string) => {
          rqdMergeCellsObj[k].forEach((l: any) => {
            formData.metas.push({
              id: this.guid(),
              字段名称: k,
              字段值: l,
              备注: "合并项目组"
            });
          });
        });
      }
      if (this.userinfo.optDay) {
        formData.metas.push({
          id: this.guid(),
          字段名称: "optDay",
          字段值: this.userinfo.optDay,
          备注: "手术日"
        });
      }
      //应用于的疾病
      if (this.multipleSelection) {
        this.multipleSelection.forEach((m: any) => {
          formData.metas.push({
            id: this.guid(),
            字段名称: m.疾病编码,
            字段值: m.名称,
            备注: "适用疾病"
          });
        });
      }

      let checkRs: string = this.beforeSave(rqdMergeCellsObj);
      if (checkRs) {
        this.$message.error(checkRs);
        return;
      }

      let rs: any = await saveTpl(formData);
      this.docId = rs.data;
      if (rs.code == 0) {
        Message({
          message: "保存成功，模板名为：" + tpl.名称,
          type: "success",
          duration: 5 * 1000
        });
      } else {
        Message({
          message: rs.msg,
          type: "error",
          duration: 5 * 1000
        });
      }
    };

    let f: any = await this.检查路径版本();
    if (f.m) {
      this.$prompt("当前路径版本已存在，是否要替换", "提示", {
        confirmButtonText: "替换",
        cancelButtonText: "取消",
        // distinguishCancelAndClose: false,
        inputValue: tpl.名称,
        closeOnClickModal: false,
        inputPattern: /\S{3,}/,
        inputErrorMessage: "至少三个字符"
      })
        .then(async (r: any) => {
          await delTpls({ ids: f.id });
          saveAction();
        })
        .catch((r: any) => {});
      return;
    }

    // if (!tpl.id) {
    this.$prompt("请输入模板名称", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      // distinguishCancelAndClose: false,
      inputValue: tpl.名称,
      closeOnClickModal: false,
      inputPattern: /\S{3,}/,
      inputErrorMessage: "至少三个字符"
    })
      .then(async (r: any) => {
        tpl.名称 = r.value;

        //如果是新建的模板，检查数据库是否存在相同名称的模板，并给出相应的提示。
        if (this.docId) {
          saveAction();
        } else {
          let r = await tplExists({ n: tpl.分组编码 });
          r = r.data;
          if (r) {
            this.$confirm(
              "已存在分组编码" + tpl.分组编码 + "的模板，是否保存？",
              "提示",
              {
                confirmButtonText: "保存",
                cancelButtonText: "取消",
                type: "warning"
              }
            )
              .then(() => {
                // tpl.id = this.docId = <any>r;
                saveAction();
              })
              .catch(() => {
                //saveAction();
              });
          } else {
            saveAction();
          }
        }
      })
      .catch(() => {
        this.$message({
          type: "info",
          message: "取消保存"
        });
      });
    // } else {
    //   saveAction();
    // }
  }
  private guid() {
    return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
      var r = (Math.random() * 16) | 0,
        v = c == "x" ? r : (r & 0x3) | 0x8;
      return v.toString(16);
    });
  }

  private async created() {
    let loading = this.$loading({ text: "loading.....", body: false });
    //通过病人信息初始化
    if (this.$route.query.id) {
      await this.initByPatid();
    }
    //通过创建的模板初始化
    if (this.$route.query.tid) {
      await this.initByTpl();
    }
    loading.close();
    // setInterval(()=>{
    //   this.费用小计合并();
    // },2000)
  }

  private getDaysBetween(dateString1: string, dateString2: string) {
    var startDate = Date.parse(dateString1);
    var endDate = Date.parse(dateString2);
    var days = (endDate - startDate) / (1 * 24 * 60 * 60 * 1000);
    return days;
  }
  private discode: string = "M47.802";

  //路径信息
  private pathWay: { discode: string; pathWayId: number } = {
    discode: "",
    pathWayId: 0
  };

  private userinfo: any = {};

  //费用信息
  private costInfo: { cost4days: any; costs: any } = {
    //每一天的项目费用
    cost4days: [],
    //单项费用
    costs: []
  };

  //当前疾病所有临床路径相关项目
  private allProjects: [] = [];

  private disePaths: any = [];
  private disePathsSize = 5;
  private disePathsPage = 1;
  private disePathsbasicCostHandleSizeChange(val: number) {
    this.disePathsSize = val;
    this.disePathsPage = 1;
  }
  private disePathsbasicCostCurrentChange(val: number) {
    this.disePathsPage = val;
    //this.selectRow();
  }

  private selectRow() {
    setTimeout(() => {
      (<any>this.$refs.multipleTable).clearSelection();
      let ls = this.disePaths.filter((it: any) => {
        return (
          this.multipleSelection.filter(
            (it2: any) => it.疾病编码 == it2.疾病编码
          ).length > 0
        );
      });

      for (let i = 0; i < ls.length; i++) {
        (<any>this.$refs.multipleTable).toggleRowSelection(ls[i], true);
      }
    }, 100);
  }

  private patwayinfo: any = {};

  private ljVersion: any = {};
  private async basicInit() {
    //“应用于以下疾病"
    let r = await DisePath({ code: this.discode });
    r = r.data;
    this.disePaths = r;

    if (this.multipleSelection && this.multipleSelection.length > 0) {
      this.selectRow();
    }

    r = await ljdir({ code: this.discode });

    this.patwayinfo = r.data || {};

    //路径版本

    if (this.$route.query.tid) {
      let ljver: any = await ljVersion({ id: this.$route.query.tid });
      ljver = ljver.data;
      this.patwayinfo = {};
      this.patwayinfo.ID = ljver.ID;
      this.patwayinfo.名称 = ljver.名称;
      this.patwayinfo.场合 = ljver.场合;
      this.ljVersion = ljver;
    } else {
      let info: any = getXVersionName(this.userinfo.drgcode);
      if (info) {
        this.patwayinfo.场合 = info.v;
      }
    }
  }

  private curTpl: any;

  private async initByTpl() {
    //模板ID
    let tplId: any = this.$route.query.tid;
    this.docId = tplId;
    let r: any = await GetTplById({ id: tplId });
    r = r.data;
    this.curTpl = r.tpl;

    //初始化病组相关信息
    r.metas
      .filter((it: any) => it.备注 == "userinfo")
      .forEach((it: any) => {
        if (!this.userinfo) this.userinfo = {};
        this.userinfo[it.字段名称] = it.字段值;
      });

    //--------使用模板的相关信息--------
    this.userinfo.discode = this.curTpl.疾病编码;
    this.userinfo.disname = this.curTpl.疾病名称;
    this.userinfo.drgcode = this.curTpl.分组编码;
    this.userinfo.drgname = this.curTpl.分组名称;
    this.userinfo.optcode = this.curTpl.手术编码;
    this.userinfo.optname = this.curTpl.手术名称;

    //初始化统计相关信息
    r.metas
      .filter((it: any) => it.备注 == "totalObj")
      .forEach((it: any) => {
        if (!this.totalObj) this.totalObj = {};
        if (!isNaN(it.字段值)) {
          this.totalObj[it.字段名称] = parseFloat(it.字段值);
        } else {
          this.totalObj[it.字段名称] = it.字段值;
        }
      });

    //适用疾病

    let 适应疾病 = r.metas.filter((it: any) => it.备注 == "适用疾病");
    if (适应疾病.length > 0) {
      this.multipleSelection = 适应疾病.map((it: any) => ({
        疾病编码: it.字段名称,
        名称: it.字段值
      }));
    }

    // this.autoProSubTypeSource = await autoProType({ n: "" });
    // this.autoProSubTypeSource = this.autoProSubTypeSource.data;

    //初始化其他元信息
    let metaObj: any = {};
    r.metas
      .filter(
        (it: any) =>
          !(
            it.备注 == "totalObj" ||
            it.备注 == "userinfo" ||
            it.备注 == "适应疾病"
          )
      )
      .forEach((it: any) => {
        metaObj[it.字段名称] = it.字段值;
      });
    //疾病编码
    this.discode = this.curTpl.疾病编码;

    if (this.userinfo.id) {
      this.initBasicPatCost(<any>this.userinfo.id);
    }

    this.basicInit();

    //天数

    let days = parseInt(metaObj.days);
    //必选项合并单元格
    let rqdMergeCells = r.metas.filter(
      (it: any) => it.字段名称 == "rqdMergeCells"
    );
    if (rqdMergeCells.length > 0) {
      this.rqdMergeCells = JSON.parse(rqdMergeCells[0].字段值);
    }
    //费用天数元数据
    let cost4days = r.metas.filter((it: any) => it.字段名称 == "cost4days");
    if (cost4days.length > 0) {
      this.costInfo.cost4days = JSON.parse(cost4days[0].字段值);
    }
    //获取当前路径所有的项目信息
    let getProTypeData: any = await getProType({ code: this.discode });
    getProTypeData = getProTypeData.data;
    this.allProjects = getProTypeData.all;

    // let 参考价格列表: any = await proc4cost({});
    // 参考价格列表 = 参考价格列表.data;
    // this.costInfo.costs = 参考价格列表;

    // this.costInfo.costs.forEach((it: any) => {
    //   this.priceObjCache[it.name] = it.price;
    // });

    let proTypes = r.data;
    proTypes.sort((a: any, b: any) => {
      return a.xh - b.xh;
    });
    //console.log('days',days,metaObj);
    this.重设天数(days);
    this.重设数据源(proTypes);

    setTimeout(() => {
      this.autoMergeRows(this.mergeCols, null);
    }, 100);
  }

  //病人基础费用
  private patBasicCost: any = [];
  private patBasicCostPage = 1;
  private patBasicCostSize = 5;
  private basicCostHandleSizeChange(val: number) {
    this.patBasicCostPage = 1;
    this.patBasicCostSize = val;
  }
  private basicCostCurrentChange(val: number) {
    this.patBasicCostPage = val;
  }
  //基础费用合计
  private patBasicCostSummaries(param: any) {
    const { columns, data } = param;
    const sums: Array<any> = [];

    let sum = (arr: Array<number>) => {
      if (!arr || arr.length == 0) return 0;
      return arr.reduce(function(prev, curr, idx, arr) {
        return prev + curr;
      });
    };

    columns.forEach((col: any, index: number) => {
      let prop = col.property;

      if (!prop) {
        sums[index] = "";
      }

      if (prop == "费用类别") {
        sums[index] = "合计";
      } else if (prop == "数量") {
        sums[index] = sum(this.patBasicCost.map((it: any) => it.数量)).toFixed(
          2
        );
      } else if (prop == "金额") {
        sums[index] = sum(this.patBasicCost.map((it: any) => it.金额)).toFixed(
          2
        );
      }
    });
    return sums;
  }

  private async initBasicPatCost(id: string) {
    //病人基础项目费用
    let bcost: any = await patBasicCostById({ id: id });
    bcost = bcost.data;
    if (bcost && bcost.length > 0) {
      this.patBasicCost = bcost;
    }
  }

  //通过病人信息数据初始化
  private async initByPatid(): Promise<void> {
    let days: number = 8;
    //小分类自动填充数据源
    this.autoProSubTypeSource = await autoProType({ n: "" });
    this.autoProSubTypeSource = this.autoProSubTypeSource.data;

    let pat4Pro: any = [];
    let ypls: any = [];

    this.initBasicPatCost(<any>this.$route.query.id);

    if (this.$route.query.id) {
      let patientData: any = await patientinfo({ id: this.$route.query.id });
      patientData = patientData.data;
      this.discode = patientData.discode;

      this.userinfo = patientData;

      //病组标植值
      let stdCostData: any = await stdCost({ code: this.userinfo.drgcode });
      stdCostData = stdCostData.data;
      if (stdCostData && stdCostData.length > 0) {
        stdCostData = stdCostData[0];

        let colMap: any = {
          cost: "平均费用",
          expended: "平均药品费",
          surveyfee: "平均检验费",
          bed: "平均床日",
          examfee: "平均检查费",
          optfee: "平均手术费",
          matfee: "平均耗材费"
        };
        Object.keys(colMap).forEach((k: string) => {
          let col: any = colMap[k];
          if (stdCostData[col]) {
            this.userinfo[k] = stdCostData[col];
          }
        });
      }

      days =
        this.getDaysBetween(
          this.userinfo.itime.split(" ")[0],
          this.userinfo.otime.split(" ")[0]
        ) + 1;

      //病人做的项目
      pat4Pro = await getProTypeByPatId({ id: this.$route.query.id });
      pat4Pro = pat4Pro.data;
      if (this.userinfo.optDate) {
        this.userinfo.optDay =
          this.getDaysBetween(
            this.userinfo.itime.split(" ")[0],
            this.userinfo.optDate.split(" ")[0]
          ) + 1;
      }

      ypls = await findProTypeAndNameByPatId({ id: this.$route.query.id });
      ypls = ypls.data;
    }

    let getProTypeData: any = await getProType({ code: this.discode });
    getProTypeData = getProTypeData.data;

    let ls = getProTypeData.ls;
    this.allProjects = getProTypeData.all;

    let proTypes: Array<any> = ls.filter((it: any) => it.proType != "药品");
    let yps = this.allProjects.filter((it: any) => it.proType == "药品");
    if (yps.length > 0) {
      proTypes.push(...yps);
    }
    //let includes = ["药品", "检验", "检查"];
    let includes = [
      "查询调档费",
      "中药饮片",
      "出诊费",
      "手术",
      "临床各系统诊疗",
      "检验",
      "挂号诊查",
      "护理治疗",
      "X线摄影胶片",
      "治疗",
      "药品",
      "模拟定位",
      "超声检查",
      "医疗机构制剂",
      "医疗机构特殊医学用途配方食品",
      "医用材料",
      "医学影像",
      "中医外治",
      "检查"
    ];
    // proTypes = proTypes.filter((it: any) => includes.includes(it.proType));
    this.pathWay = { pathWayId: getProTypeData.pathWay, discode: this.discode };

    let 参考价格列表: any = await proc4cost({});
    参考价格列表 = 参考价格列表.data;
    this.costInfo.costs = 参考价格列表;
    this.costInfo.costs.forEach((it: any) => {
      this.priceObjCache[it.name] = it.price;
    });
    let itime: string = this.userinfo.itime;
    itime = itime.split(" ")[0];

    //1.将检验、检查做了的对上
    if (pat4Pro.length > 0) {
      let 检验and检查 = pat4Pro.filter((it: any) => {
        return !["药品"].includes(it.proType);
      });

      检验and检查.forEach((it: any) => {
        let ps = proTypes.filter((p: any) => {
          return p.proType == it.proType && p.proSubType == it.proSubType;
        });

        //如果不是检验检查滴，应该添加进项目
        if (ps.length == 0) {
          let o: any = {
            proType: it.proType,
            proSubType: it.proSubType,
            attr: it.attr
          };
          proTypes.push(o);
          if (it.proType == "医用材料") {
            o.name = it.name;
          }
          ps = proTypes.filter((p: any) => {
            return p.proType == it.proType && p.proSubType == it.proSubType;
          });
        }
        ps.forEach((p: any) => {
          let day = this.getDaysBetween(itime, it.ts);
          day += 1;
          p[`days${day}`] = "√";
          p.used = true;
        });
        let day4cost = JSON.parse(JSON.stringify(it));
        day4cost.ts = this.getDaysBetween(itime, it.ts) + 1;

        let 单项参考费用 = 参考价格列表.filter(
          (pric: any) =>
            pric.proType == it.proType && pric.proSubType == it.proSubType
        );
        if (单项参考费用.length > 0) 单项参考费用 = 单项参考费用[0];
        day4cost.amount = day4cost.num * (单项参考费用.price || 0);
        //天数费用信息处理
        this.costInfo.cost4days.push(day4cost);
      });
    }
    //天数打勾、必选赋初值

    let 版本 = this.vn(this.userinfo.drgcode);

    proTypes.forEach((it: any) => {
      //it.rqd = it.rqd >= 2;
      //手术必选，在外科组、操作组，就是必选，内科组就是可选；必须就是必选，可选就是可选
      if (it.rqd == "3" && 版本 != "内科版") {
        it.rqd = true;
      } else if (it.rqd == "3" && 版本 == "内科版") {
        it.rqd = false;
      } else it.rqd = it.rqd >= 2;

      it.mark = it.attr == "2" ? "不判断" : "";
    });

    this.basicInit();

    //按病人初始化时用proType ProSubType排序
    let colMap: any = { 药品: 1, 检验: 2, 检查: 3, 治疗: 4 };
    proTypes.sort((a: any, b: any) => {
      let n1: number = colMap[a.proType] || this.hashcode(a.proType);
      let n2: number = colMap[b.proType] || this.hashcode(b.proType);
      if (n1 == n2) {
        return a.proSubType.localeCompare(b.proSubType);
      }
      return n1 - n2;
    });
    proTypes.forEach((it: any, i: number) => {
      it.xh = i + 1;
    });

    this.重设天数(days);

    this.重设数据源(proTypes);
    setTimeout(() => {
      this.autoMergeRows(this.mergeCols, null);
    }, 100);
  }
  private multipleSelection: any;

  private getRowKeys(row: any) {
    return row.疾病编码;
  }
  //应用于以下疾病选中
  private handleSelectionChange(val: any) {
    this.multipleSelection = val;
  }

  /**
  获取版本号
  //  */
  private vn(code: string) {
    return getVersionName(code);
  }

  private distinctProType(ls: Array<any>) {
    var rs: any = [];
    ls.forEach((it: any) => {
      if (
        rs.filter(
          (it2: any) =>
            it2.proType == it.proType && it2.proSubType == it.proSubType
        ).length == 0
      ) {
        rs.push(it);
      }
    });
    return rs;
  }
}
</script>

<style lang="scss">
#hot {
  table,
  table tr th,
  table tr td {
    /***解决handsontable默认合并单元格元边框的BUG问题 */
    border: 1px solid #ccc !important;
  }
  table {
    width: 100%;
    min-height: 25px;
    line-height: 25px;
    text-align: center;
    border-collapse: collapse;
    padding: 2px;
  }
  .lexits {
    color: #0000cd !important;
    .htDimmed {
      color: #0000cd !important;
    }
  }
  td {
    min-width: 100px;
    max-width: 250px;
  }
  td:nth-child(n + 7) {
    font-weight: bold;
    font-size: 18px !important;
  }
  .colheaderred {
    color: red;
    font-weight: bold;
  }
  .htCenter {
    font-size: 16px !important;
  }
}
.costColorBlue {
  color: blue;
}
.costColorRed {
  color: red;
}
.htCommentCell:after {
  border-top: 6px solid red;
}
.el-descriptions-item__container {
  font-size: 16px !important;
  font-weight: bold;
}
</style>
